home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -in_the_mag- / program_perfection / event / event_demo.c < prev    next >
C/C++ Source or Header  |  2000-03-14  |  6KB  |  277 lines

  1. /*
  2.  * The beginnings of the event-handling module
  3.  * we talked of long ago . . .
  4.  *
  5.  * Richard Drummond 11/3/2000
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <exec/lists.h>
  10. #include <exec/ports.h>
  11.  
  12. #include <dos/dos.h>
  13.  
  14. #include <intuition/intuition.h>
  15.  
  16. #include <proto/exec.h>
  17. #include <proto/dos.h>
  18. #include <proto/intuition.h>
  19.  
  20.  
  21. /*
  22.  * Private types
  23.  */
  24.  
  25. typedef ULONG (*HANDLER_FUNC) (UBYTE, struct MsgPort *);
  26.  
  27.  
  28. typedef struct EventHandler
  29. {
  30.     struct MinNode   eh_Node;
  31.     UBYTE            eh_pad;
  32.     BYTE             eh_SignalNumber;   /* equivalent to ln_Pri */
  33.     struct MsgPort  *eh_MsgPort;        /* Where messages for this event arrive */
  34.     HANDLER_FUNC     eh_HandlerFunc;    /* Function to handle this event */
  35. } HANDLER_TYPE;
  36.  
  37. typedef HANDLER_TYPE *HANDLER_PTR;
  38.  
  39.  
  40. struct EventList
  41. {
  42.     struct MinList  el_HandlerList;
  43.     ULONG           el_SignalMask;      /* all the singals we wait for */
  44. };
  45.  
  46.  
  47.  
  48.  
  49.  
  50. /*
  51.  * EventList_AddHandler()
  52.  *
  53.  * list   - the list we wish to add to
  54.  * signum - the signal that flags this event. if this is not in the range
  55.  *          0 to 31, then we get the signal bit from the msgport.
  56.  * port   - the port that this event's messages arrive at (if any)
  57.  * hfunc  - function to call when event occurs
  58.  */
  59.  
  60. BOOL
  61. EventList_AddHandler( struct EventList *list, UBYTE signum, struct MsgPort *port, HANDLER_FUNC hfunc )
  62. {
  63.     HANDLER_TYPE *handler;
  64.  
  65.     if( signum > 31 )
  66.         signum = port->mp_SigBit;
  67.  
  68.     if( handler = (HANDLER_TYPE *) AllocVec( sizeof(HANDLER_TYPE), MEMF_ANY | MEMF_CLEAR ) )
  69.     {
  70.         handler->eh_SignalNumber = signum;
  71.         handler->eh_MsgPort      = port;
  72.         handler->eh_HandlerFunc  = hfunc;
  73.  
  74.         Enqueue( (struct List *) list, (struct Node *) handler );
  75.  
  76.         list->el_SignalMask |= 1L << signum;
  77.     }
  78.  
  79.     return !!handler;
  80. }
  81.  
  82.  
  83. /*
  84.  * EventList_RemHnadler()
  85.  */
  86. VOID
  87. EventList_RemHandler( struct EventList *list, UBYTE signum )
  88. {
  89.     struct Node *node  = ((struct List *) list)->lh_Head;
  90.     BOOL         found = FALSE;
  91.  
  92.     while( node->ln_Succ && !found )
  93.     {
  94.         if( found = ( ((HANDLER_PTR)node)->eh_SignalNumber == signum ) )
  95.             break;
  96.         else
  97.             node = node->ln_Succ;
  98.     }
  99.  
  100.     if( found )
  101.     {
  102.         list->el_SignalMask &= ~( 1L << ((HANDLER_PTR)node)->eh_SignalNumber );
  103.         Remove( node );
  104.         FreeVec( node );
  105.     }
  106. }
  107.  
  108. /*
  109.  * EventList_New()
  110.  *
  111.  * Constructor for the EventList type
  112.  */
  113. struct EventList *
  114. EventList_New( VOID )
  115. {
  116.     struct EventList *list;
  117.  
  118.     if( list = AllocVec( sizeof(struct EventList), MEMF_ANY ) )
  119.     {
  120.         NewList( (struct List *) list );
  121.         list->el_SignalMask = 0L;
  122.     }
  123.  
  124.     return list;
  125. }
  126.  
  127. /*
  128.  * EventList_Dispose()
  129.  *
  130.  * Destructor for the EventList type
  131.  */
  132. VOID
  133. EventList_Dispose( struct EventList *list )
  134. {
  135.     if( list )
  136.     {
  137.         struct Node *node, *temp;
  138.  
  139.         node = ((struct List *) list)->lh_Head;
  140.  
  141.         while( temp = node->ln_Succ )
  142.         {
  143.             FreeVec( node );
  144.             node = temp;
  145.         }
  146.  
  147.         NewList( (struct List *) list );
  148.         list->el_SignalMask = 0L;
  149.  
  150.         FreeVec( list );
  151.     }
  152. }
  153.  
  154.  
  155. /*
  156.  * EventList_Process()
  157.  *
  158.  * This is where it all happens.
  159.  * Put's the current process to sleep until one of the
  160.  * events in the list occurs. Then take some action
  161.  */
  162. ULONG
  163. EventList_Process( struct EventList *list )
  164. {
  165.     ULONG        got_sigs;
  166.     ULONG        wait_sigs = list->el_SignalMask;
  167.     struct Node *node      = ((struct List *) list)->lh_Head;
  168.     ULONG        ret       = 0L;
  169.  
  170.     if( wait_sigs )
  171.     {
  172.         got_sigs = Wait( list->el_SignalMask );
  173.  
  174.         while( node->ln_Succ )
  175.         {
  176.             if( got_sigs & ( 1 << ((HANDLER_PTR)node)->eh_SignalNumber ) )
  177.             {
  178.                 Printf( "Received signal: %ld\n", ((HANDLER_PTR)node)->eh_SignalNumber );
  179.  
  180.                 if( ((HANDLER_PTR)node)->eh_HandlerFunc )
  181.                     ret = ((HANDLER_PTR)node)->eh_HandlerFunc( 0L, ((HANDLER_PTR)node)->eh_MsgPort );
  182.             }
  183.             node = node->ln_Succ;
  184.         }
  185.     }
  186.  
  187.     return ret;
  188. }
  189.  
  190.  
  191. /*
  192.  * HandlerBreak()
  193.  *
  194.  * A simple handler for break signals
  195.  */
  196. ULONG
  197. HandleBreak( UBYTE signal, struct MsgPort *port )
  198. {
  199.     Printf( "**Break\n" );
  200.     return 1L;
  201. }
  202.  
  203. /*
  204.  * HandleWindow()
  205.  *
  206.  * A simple handler for ordinary intuition windows
  207.  * It is not designed for use with a shared IDCMP port
  208.  */
  209. ULONG
  210. HandleWindow( UBYTE signal, struct MsgPort *port )
  211. {
  212.     struct IntuiMessage *temp_msg;
  213.     struct IntuiMessage  imsg;
  214.     ULONG                ret = 0L;
  215.  
  216.     if( temp_msg = (struct IntuiMessage *) GetMsg( port ) )
  217.     {
  218.         Printf( "IntuiMessage (Class:%08lx Code:%08lx)\n", temp_msg->Class, temp_msg->Code );
  219.  
  220.         /*
  221.          * Here we react to this message . . .
  222.          *
  223.          * e.g., check for the close gadget
  224.          */
  225.         if( temp_msg->Class == IDCMP_CLOSEWINDOW )
  226.             ret=1L;
  227.  
  228.         ReplyMsg( (struct Message *) temp_msg );
  229.     }
  230.     return ret;
  231. }
  232.  
  233.  
  234. /*
  235.  * A quick test . . .
  236.  */
  237. int main(void)
  238. {
  239.     struct EventList *list;
  240.  
  241.     if( list = EventList_New() )
  242.     {
  243.         struct Window *w;
  244.  
  245.         if( w = OpenWindowTags( NULL, WA_Height, 200,
  246.                                       WA_Width, 200,
  247.                                       WA_CloseGadget, TRUE,
  248.                                       WA_DragBar, TRUE,
  249.                                       WA_SizeGadget, TRUE,
  250.                                       WA_SizeBBottom, TRUE,
  251.                                       WA_DepthGadget, TRUE,
  252.                                       WA_Title, "Event handling demo",
  253.                                       WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_CHANGEWINDOW | IDCMP_RAWKEY,
  254.                                   TAG_DONE ) )
  255.         {
  256.  
  257.             EventList_AddHandler( list, -1, w->UserPort, HandleWindow );
  258.             EventList_AddHandler( list, SIGBREAKB_CTRL_C, NULL, HandleBreak );
  259.             EventList_AddHandler( list, SIGBREAKB_CTRL_D, NULL, NULL );
  260.             EventList_AddHandler( list, SIGBREAKB_CTRL_E, NULL, NULL );
  261.             EventList_AddHandler( list, SIGBREAKB_CTRL_F, NULL, NULL );
  262.  
  263.             Printf("Try pressing CTRL-C/D/E/F in this window or moving the Demo window\n");
  264.  
  265.             while( !EventList_Process( list ) )
  266.                 ;
  267.  
  268.             CloseWindow( w );
  269.         }
  270.     }
  271.  
  272.     EventList_Dispose( list );
  273.  
  274.     return 0L;
  275. }
  276.  
  277.